﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using THO7AlgorithmBase;

namespace OCR_LEARN
{
    class TjerkOCR
    {
        float[] normalizedColumns = new float[20];
        float[] normalizedRows = new float[20];
        /// <summary>
        /// converts an integer array to a normalized array of floats
        /// </summary>
        /// <param name="intArray">integer array containing the integers to be normalized</param>
        /// <param name="bins">amount of bins for the normalized integers</param>
        /// <returns></returns>
        private float[] normalizeIntArrayToFloats(int[] intArray, int bins)
        {
            float[] normalized = new float[intArray.Length];
            int intArraySum = 0;

            foreach (int i in intArray)
            {
                intArraySum += i;
            }
            for (int i = 0; i < intArray.Length; i++)
            {
                normalized[i] = ((float)intArray[i] / (float)intArraySum);
            }

            float[] normalizedBins = new float[bins];
            int step = intArray.Length / bins;
            int stepper = 0;
            for (int i = 0; i < bins; i++)
            {
                for (int ii = 0; ii < step; ii++)
                {
                    normalizedBins[i] += normalized[stepper++];
                }
            }
            return normalizedBins;
        }
        /// <summary>
        /// crops away the white edges closing in the sides until a black pixel is found
        /// rezises the bitmap to the given width and height 
        /// </summary>
        /// <param name="inputBitmap"></param>
        /// <param name="newWidth"></param>
        /// <param name="newHeight"></param>
        /// <returns>rezized cropped bitmap</returns>
        private Bitmap cropAndResize(Bitmap inputBitmap, int newWidth, int newHeight)
        {
            //from top to bottom
            Boolean stop = false;
            int top = 0;
            for (int i = 1; (i < inputBitmap.Height) && !stop; i++)
            {

                for (int ii = 1; (ii < inputBitmap.Width); ii++)
                {
                    if (inputBitmap.GetPixel(ii, i) == Color.FromArgb(255, 0, 0, 0))
                    {
                        top = i;
                        stop = true;
                        break;
                    }
                }
            }

            //from bottom to top
            stop = false;
            int bottom = 0;
            for (int i = inputBitmap.Height - 1; (i > 0) && !stop; i--)
            {
                for (int ii = 1; (ii < inputBitmap.Width); ii++)
                {
                    if (inputBitmap.GetPixel(ii, i) == Color.FromArgb(255, 0, 0, 0))
                    {
                        bottom = i;
                        stop = true;
                        break;
                    }
                }
            }

            //from right to left
            stop = false;
            int right = 0;
            for (int i = inputBitmap.Width - 1; (i > 0) && !stop; i--)
            {
                for (int ii = 1; (ii < inputBitmap.Height); ii++)
                {
                    if (inputBitmap.GetPixel(i, ii) == Color.FromArgb(255, 0, 0, 0))
                    {
                        right = i;
                        stop = true;
                        break;
                    }
                }
            }

            //from left to right
            stop = false;
            int left = 0;
            for (int i = 1; (i < inputBitmap.Width) && !stop; i++)
            {
                for (int ii = 1; (ii < inputBitmap.Height); ii++)
                {
                    if (inputBitmap.GetPixel(i, ii) == Color.FromArgb(255, 0, 0, 0))
                    {
                        left = i;
                        stop = true;
                        break;
                    }
                }
            }

            Rectangle rect = new Rectangle(left, top, inputBitmap.Width - (left + (inputBitmap.Width - right)), inputBitmap.Height - (top + (inputBitmap.Height - bottom)));
            Bitmap temp = inputBitmap.Clone(rect, inputBitmap.PixelFormat);

            Bitmap outputBitmap = new Bitmap(newWidth, newHeight);
            using (Graphics g = Graphics.FromImage((Image)outputBitmap)) g.DrawImage(temp, 0, 0, newWidth, newHeight);
            return outputBitmap;
        }
        /// <summary>
        /// rezises the bitmap to the given width and height 
        /// </summary>
        /// <param name="inputBitmap"></param>
        /// <param name="newWidth"></param>
        /// <param name="newHeight"></param>
        /// <returns>rezized bitmap</returns>
        private Bitmap justResize(Bitmap inputBitmap, int newWidth, int newHeight)
        {
            Bitmap outputBitmap = new Bitmap(newWidth, newHeight);
            using (Graphics g = Graphics.FromImage((Image)outputBitmap)) g.DrawImage(inputBitmap, 0, 0, newWidth, newHeight);
            return outputBitmap;
        }
        public void learn(Bitmap inputImage, String character)
        {
            if (inputImage != null)
            {
                Bitmap inputBitmap = (Bitmap)inputImage;

                //the image dimensions must be divisible by the number of bins used in the normalisation
                Bitmap outputBitmap = justResize(inputBitmap, 400, 400);

                int threshold = 50;
                Color tempColor;
                //count black pixels per row from top to bottom
                int[] rows = new int[outputBitmap.Height];
                for (int i = 1; (i < outputBitmap.Height); i++)
                {
                    int row = 0;
                    for (int ii = 1; (ii < outputBitmap.Width); ii++)
                    {
                        tempColor = outputBitmap.GetPixel(i, ii);
                        if (((tempColor.R == tempColor.G) && (tempColor.G == tempColor.B)) && (tempColor.R + tempColor.G + tempColor.B) <= threshold)
                        {
                            row++;
                        }
                    }
                    rows[i - 1] = row;
                }
                //count black pixels per column from left to right
                int[] columns = new int[outputBitmap.Width];
                for (int i = 1; (i < outputBitmap.Width); i++)
                {
                    int column = 0;
                    for (int ii = 1; (ii < outputBitmap.Height); ii++)
                    {
                        tempColor = outputBitmap.GetPixel(ii, i);
                        if (((tempColor.R == tempColor.G) && (tempColor.G == tempColor.B)) && (tempColor.R + tempColor.G + tempColor.B) <= threshold)
                        {
                            outputBitmap.SetPixel(ii, i, Color.Red);
                            column++;
                        }
                    }
                    columns[i - 1] = column;
                }

                //NORMALISATION
                normalizedRows = normalizeIntArrayToFloats(rows, 20);
                normalizedColumns = normalizeIntArrayToFloats(columns, 20);

                System.IO.StreamWriter learningFile = new System.IO.StreamWriter(@"tjerkocr.txt", true);
                learningFile.Write(character + ";");
                foreach (float f in normalizedColumns)
                {
                    learningFile.Write(f + ":");
                }
                foreach (float f in normalizedRows)
                {
                    learningFile.Write(f + ":");
                }
                learningFile.WriteLine("");
                learningFile.Close();

            }
        }
    }
}
